﻿namespace UnityEngine
{
    using System;
    using System.Collections;

    internal class InternalStaticBatchingUtility
    {
        private const string CombinedMeshPrefix = "Combined Mesh";
        private const int MaxVerticesInBatch = 0xfa00;

        public static void Combine(GameObject staticBatchRoot, bool generateTriangleStrips)
        {
            Combine(staticBatchRoot, false, generateTriangleStrips);
        }

        public static void Combine(GameObject staticBatchRoot, bool combineOnlyStatic, bool generateTriangleStrips)
        {
            GameObject[] gos = (GameObject[]) UnityEngine.Object.FindObjectsOfType(typeof(GameObject));
            ArrayList list = new ArrayList();
            foreach (GameObject obj2 in gos)
            {
                if (((staticBatchRoot == null) || obj2.transform.IsChildOf(staticBatchRoot.transform)) && (!combineOnlyStatic || obj2.isStaticBatchable))
                {
                    list.Add(obj2);
                }
            }
            gos = (GameObject[]) list.ToArray(typeof(GameObject));
            if ((!(Application.HasProLicense() || Application.HasAdvancedLicense()) && (staticBatchRoot != null)) && (gos.Length > 0))
            {
                Debug.LogError("Your Unity license is not sufficient for Static Batching.");
            }
            Combine(gos, staticBatchRoot, generateTriangleStrips);
        }

        public static void Combine(GameObject[] gos, GameObject staticBatchRoot, bool generateTriangleStrips)
        {
            Matrix4x4 identity = Matrix4x4.identity;
            Transform staticBatchRootTransform = null;
            if (staticBatchRoot != null)
            {
                identity = staticBatchRoot.transform.worldToLocalMatrix;
                staticBatchRootTransform = staticBatchRoot.transform;
            }
            int batchIndex = 0;
            int num2 = 0;
            ArrayList meshes = new ArrayList();
            ArrayList subsets = new ArrayList();
            Array.Sort(gos, new SortGO());
            foreach (GameObject obj2 in gos)
            {
                MeshFilter component = obj2.GetComponent(typeof(MeshFilter)) as MeshFilter;
                if ((((component != null) && (component.sharedMesh != null)) && (component.sharedMesh.canAccess && (component.renderer != null))) && (component.renderer.enabled && (component.renderer.staticBatchIndex == 0)))
                {
                    if ((num2 + component.sharedMesh.vertexCount) > 0xfa00)
                    {
                        MakeBatch(meshes, subsets, staticBatchRootTransform, batchIndex++, generateTriangleStrips);
                        meshes.Clear();
                        subsets.Clear();
                        num2 = 0;
                    }
                    MeshSubsetCombineUtility.MeshInstance instance = new MeshSubsetCombineUtility.MeshInstance {
                        mesh = component.sharedMesh,
                        transform = identity * component.transform.localToWorldMatrix,
                        lightmapTilingOffset = component.renderer.lightmapTilingOffset
                    };
                    meshes.Add(instance);
                    Material[] sharedMaterials = component.renderer.sharedMaterials;
                    if (sharedMaterials.Length > instance.mesh.subMeshCount)
                    {
                        Debug.LogWarning(string.Concat(new object[] { "Mesh has more materials (", sharedMaterials.Length, ") than subsets (", instance.mesh.subMeshCount, ")" }));
                        Material[] materialArray2 = new Material[instance.mesh.subMeshCount];
                        for (int j = 0; j < instance.mesh.subMeshCount; j++)
                        {
                            materialArray2[j] = component.renderer.sharedMaterials[j];
                        }
                        component.renderer.sharedMaterials = materialArray2;
                        sharedMaterials = materialArray2;
                    }
                    for (int i = 0; i < Math.Min(sharedMaterials.Length, instance.mesh.subMeshCount); i++)
                    {
                        MeshSubsetCombineUtility.SubMeshInstance instance2 = new MeshSubsetCombineUtility.SubMeshInstance {
                            mesh = component.sharedMesh,
                            vertexOffset = num2,
                            subMeshIndex = i,
                            gameObject = obj2,
                            transform = instance.transform
                        };
                        subsets.Add(instance2);
                    }
                    num2 += instance.mesh.vertexCount;
                }
            }
            MakeBatch(meshes, subsets, staticBatchRootTransform, batchIndex, generateTriangleStrips);
        }

        private static void MakeBatch(ArrayList meshes, ArrayList subsets, Transform staticBatchRootTransform, int batchIndex, bool generateTriangleStrips)
        {
            if (meshes.Count >= 2)
            {
                MeshSubsetCombineUtility.MeshInstance[] instanceArray = (MeshSubsetCombineUtility.MeshInstance[]) meshes.ToArray(typeof(MeshSubsetCombineUtility.MeshInstance));
                MeshSubsetCombineUtility.SubMeshInstance[] submeshes = (MeshSubsetCombineUtility.SubMeshInstance[]) subsets.ToArray(typeof(MeshSubsetCombineUtility.SubMeshInstance));
                string meshName = "Combined Mesh";
                meshName = meshName + " (root: " + ((staticBatchRootTransform == null) ? "scene" : staticBatchRootTransform.name) + ")";
                if (batchIndex > 0)
                {
                    meshName = meshName + " " + (batchIndex + 1);
                }
                Mesh combinedMesh = StaticBatchingUtility.InternalCombineVertices(instanceArray, meshName);
                StaticBatchingUtility.InternalCombineIndices(submeshes, generateTriangleStrips, ref combinedMesh);
                int subSetIndexForMaterial = 0;
                foreach (MeshSubsetCombineUtility.SubMeshInstance instance in submeshes)
                {
                    GameObject gameObject = instance.gameObject;
                    Mesh mesh2 = combinedMesh;
                    MeshFilter component = (MeshFilter) gameObject.GetComponent(typeof(MeshFilter));
                    component.sharedMesh = mesh2;
                    gameObject.renderer.SetSubsetIndex(instance.subMeshIndex, subSetIndexForMaterial);
                    gameObject.renderer.staticBatchRootTransform = staticBatchRootTransform;
                    gameObject.renderer.enabled = false;
                    gameObject.renderer.enabled = true;
                    subSetIndexForMaterial++;
                }
            }
        }

        internal class SortGO : IComparer
        {
            private static int GetLightmapIndex(UnityEngine.Renderer renderer)
            {
                if (renderer == null)
                {
                    return -1;
                }
                return renderer.lightmapIndex;
            }

            private static int GetMaterialId(UnityEngine.Renderer renderer)
            {
                if (renderer == null)
                {
                    return 0;
                }
                return renderer.sharedMaterial.GetInstanceID();
            }

            private static UnityEngine.Renderer GetRenderer(GameObject go)
            {
                if (go == null)
                {
                    return null;
                }
                MeshFilter component = go.GetComponent(typeof(MeshFilter)) as MeshFilter;
                if (component == null)
                {
                    return null;
                }
                return component.renderer;
            }

            int IComparer.Compare(object a, object b)
            {
                if (a == b)
                {
                    return 0;
                }
                UnityEngine.Renderer renderer = GetRenderer(a as GameObject);
                UnityEngine.Renderer renderer2 = GetRenderer(b as GameObject);
                int num = GetMaterialId(renderer).CompareTo(GetMaterialId(renderer2));
                if (num == 0)
                {
                    num = GetLightmapIndex(renderer).CompareTo(GetLightmapIndex(renderer2));
                }
                return num;
            }
        }
    }
}

